﻿using System.Collections.Generic;
using System.Linq;
using System.Management;
using ClusterAwareProperties;

namespace ClusterAwareWMI
{
    /// <summary>
    /// Helpper Class to Access WMI Objects
    /// </summary>
    internal class ClusterWmiHelpper
    {

        ///<summary>
        /// Return Operation System
        ///</summary>
        /// <param name="scope">instance of ManagementScope</param>
        ///<returns>Enum WindowsOperationSystem</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// Not Connected, 
        /// Failed WMI method execution
        /// </exception>
        internal WindowsOperationSystem GetOperationSystem(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var scopeclone = scope.Clone();
            scopeclone.Path = new ManagementPath(scope.Path.ToString().Replace("root\\MSCluster", "root\\CIMV2"));
            var searcher =
                new ManagementObjectSearcher(scopeclone,
                                             new ObjectQuery("select * from Win32_OperatingSystem"));
            var result =
                (from ManagementObject queryObj in searcher.Get() select queryObj).
                    FirstOrDefault();
            var ret = WindowsOperationSystem.Unknown;
            if (result != null)
            {
                switch (result["Version"].ToString().Substring(0, 1))
                {
                    case "5":
                        {
                            ret = result["ServicePackMajorVersion"].ToString() == "2" ? WindowsOperationSystem.Windows2003R2 : WindowsOperationSystem.Windows2003;
                        }
                        break;
                    case "6":
                        {
                            if (result["Version"].ToString().Substring(0, 3) == "6.0")
                            {
                                ret = WindowsOperationSystem.Windows2008;
                            }
                            if (result["Version"].ToString().Substring(0, 3) == "6.1")
                            {
                                ret = WindowsOperationSystem.Windows2008R2;
                            }
                        }
                        break;
                }
            }
            return ret;
        }


        /// <summary>
        /// Return ManagementScope 
        /// </summary>
        ///<param name="scope">Scope WMI</param>
        ///<param name="domain">Doamin where cluster is running</param>
        ///<param name="machine">Machine or Cluster name</param>
        ///<param name="userName">Username to connect</param>
        ///<param name="password">Password to connect</param>
        ///<param name="authenticationLevel">Authentication Level enumeration</param>
        /// <returns>ManagementScope connected</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// Not Connected, 
        /// Failed WMI method execution
        /// </exception>       
        internal ManagementScope GetScope(string scope, string domain, string machine, string userName, string password, AuthenticationLevel authenticationLevel)
        {
            var connection = new ConnectionOptions
            {
                Authentication = authenticationLevel
            };
            if (userName != null)
            {
                connection.Username = userName;
            }
            if (password != null)
            {
                connection.Password = password;
            }
            if (domain != null)
            {
                connection.Authority = string.Format("ntlmdomain:{0}", domain);
            }
            var scopeResult = new ManagementScope(scope, connection);
            scopeResult.Connect();
            return scopeResult;
        }

        /// <summary>
        /// Get list of Group
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of Group class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal GroupProperty[] GetGroups(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<GroupProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_ResourceGroup"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new GroupProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a Group 
        /// </summary>
        /// <param name="groupName">Group Name</param>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Group Class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal GroupProperty GetGroup(string groupName, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope,
                new ObjectQuery("SELECT * FROM MSCluster_ResourceGroup where Name='" + groupName + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new GroupProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get a resource list
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of resource class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceProperty[] GetResources(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                           new ManagementObjectSearcher(scope, new ObjectQuery(
                           "SELECT * FROM MSCluster_Resource"));
            return (from ManagementObject queryObj in searcher.Get() select new ResourceProperty(queryObj)).ToArray();
        }

        /// <summary>
        /// Get a active resource list from a node
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameNode">Node name</param>
        /// <returns>Array of resource class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceProperty[] FindActiveResourcesByNode(string nameNode, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_NodeToActiveResource WHERE GroupComponent = \"MSCluster_Node.Name='" + nameNode + "'\""));
            var reslst = (from ManagementObject s in searcher.Get()
                          select s["PartComponent"].ToString().Replace("MSCluster_Resource.Name=\"", "").Replace("\"", "")).ToList();
            return reslst.Select(res => GetResource(res.Replace("\\\\", "\\"), scope)).ToArray();
        }

        /// <summary>
        /// Get a active group list from a node
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameNode">Node name</param>
        /// <returns>Array of group class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal GroupProperty[] FindActiveGroupsByNode(string nameNode, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_NodeToActiveGroup WHERE GroupComponent = \"MSCluster_Node.Name='" + nameNode + "'\""));
            var grplst = (from ManagementObject s in searcher.Get()
                          select s["PartComponent"].ToString().Replace("MSCluster_ResourceGroup.Name=\"", "").Replace("\"", "")).ToList();
            return grplst.Select(grp => GetGroup(grp.Replace("\\\\", "\\"), scope)).ToArray();
        }

        /// <summary>
        /// Get a node from a group
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameGroup">group name</param>
        /// <returns>node class of group</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NodeProperty FindActiveNodeByGroup(string nameGroup, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_NodeToActiveGroup WHERE PartComponent = \"MSCluster_ResourceGroup.Name='" + nameGroup + "'\""));
            var node = (from ManagementObject s in searcher.Get()
                        select s["GroupComponent"].ToString().Replace("MSCluster_Node.Name=\"", "").Replace("\"", "")).
                FirstOrDefault();
            return GetNode(node, scope);
        }


        /// <summary>
        /// Get a networkInterface list from a node
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameNode">Node name</param>
        /// <returns>Array of networkInterface class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NetworkInterfaceProperty[] FindNetworkInterfacesByNode(string nameNode, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_NodeToNetworkInterface WHERE GroupComponent = \"MSCluster_Node.Name='" + nameNode + "'\""));
            var netlst = (from ManagementObject s in searcher.Get()
                          select s["PartComponent"].ToString().Replace("MSCluster_NetworkInterface.DeviceID=", "").Replace("\"", "").Split(',')[0]).ToList();
            return netlst.Select(net => GetNetworkInterface(net, scope)).ToArray();
        }


        /// <summary>
        /// Get a resource list from a group
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameGroup">Group name</param>
        /// <returns>Array of resource class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceProperty[] FindResourcesByGroup(string nameGroup, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_ResourceGroupToResource WHERE GroupComponent = \"MSCluster_ResourceGroup.Name='" + nameGroup + "'\""));
            var resgrp = (from ManagementObject s in searcher.Get()
                          select s["PartComponent"].ToString().Replace("MSCluster_Resource.Name=\"", "").Replace("\"", "")).ToList();
            return resgrp.Select(res => GetResource(res.Replace("\\\\", "\\"), scope)).ToArray();
        }

        /// <summary>
        /// Get a node list from a group
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameGroup">Group name</param>
        /// <returns>Array of node class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NodeProperty[] FindPreferredNodeByGroup(string nameGroup, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_ResourceGroupToPreferredNode WHERE GroupComponent = \"MSCluster_ResourceGroup.Name='" + nameGroup + "'\""));
            var nodes = (from ManagementObject s in searcher.Get()
                         select s["PartComponent"].ToString().Replace("MSCluster_Node.Name=\"", "").Replace("\"", "")).ToList();
            return nodes.Select(n => GetNode(n, scope)).ToArray();
        }


        /// <summary>
        /// Get a resource 
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameResource">Resource name</param>
        /// <returns>Resource class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceProperty GetResource(string nameResource, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
               new ManagementObjectSearcher(scope, new ObjectQuery(
               "SELECT * FROM MSCluster_Resource where Name = '" + nameResource.Replace("\\", "\\\\") + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new ResourceProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get list of Nodes
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of Node class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NodeProperty[] GetNodes(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<NodeProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_Node"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new NodeProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a Node 
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameNode">Node name</param>
        /// <returns>Node class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NodeProperty GetNode(string nameNode, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope, new ObjectQuery(
                                                        "SELECT * FROM MSCluster_Node where Name ='" + nameNode + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new NodeProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get list of ResourceType
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of ResourceType class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceTypeProperty[] GetResourceTypes(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<ResourceTypeProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_ResourceType"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new ResourceTypeProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a Resource Type
        /// </summary>
        /// <param name="nameResourcetype">Resourcetype name</param>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>ResourceType class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceTypeProperty GetResourceType(string nameResourcetype, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope, new ObjectQuery(
                                                        "SELECT * FROM MSCluster_ResourceType  where Name ='" + nameResourcetype + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new ResourceTypeProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get list of Network
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of Network class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NetworkProperty[] GetNetworks(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<NetworkProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_Network"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new NetworkProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a Network
        /// </summary>
        /// <param name="nameNetwork">Network name</param>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Network class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NetworkProperty GetNetwork(string nameNetwork, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope, new ObjectQuery(
                                                        "SELECT * FROM MSCluster_Network  where Name ='" + nameNetwork + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new NetworkProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get list of Disk
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of Disk class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal DiskProperty[] GetDisks(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<DiskProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_Disk"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new DiskProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a Disk 
        /// </summary>
        /// <param name="diskName">Disk Name</param>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Disk Class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal DiskProperty GetDisk(string diskName, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope,
                new ObjectQuery("SELECT * FROM MSCluster_Disk where Name='" + diskName + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new DiskProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get list of Disk
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of Available class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal DiskProperty[] GetAvailableDisks(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<DiskProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_AvailableDisk"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new DiskProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a Disk 
        /// </summary>
        /// <param name="diskName">AvailableDisk Name</param>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Disk Class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal DiskProperty GetAvailableDisk(string diskName, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope,
                new ObjectQuery("SELECT * FROM MSCluster_AvailableDiskwhere Name='" + diskName + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new DiskProperty(queryObj)).FirstOrDefault();
        }

        /// <summary>
        /// Get list of NetworkInterface
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>Array of NetworkInterface class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NetworkInterfaceProperty[] GetNetworkInterfaces(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var result = new List<NetworkInterfaceProperty>();
            var searcher =
               new ManagementObjectSearcher(scope,
               new ObjectQuery("SELECT * FROM MSCluster_NetworkInterface"));
            result.AddRange(from ManagementObject queryObj in searcher.Get() select new NetworkInterfaceProperty(queryObj));
            return result.ToArray();
        }

        /// <summary>
        /// Get a NetworkInterface
        /// </summary>
        /// <param name="nameNetwork">NetworkInterface name</param>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>NetworkInterface class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NetworkInterfaceProperty GetNetworkInterface(string nameNetwork, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope, new ObjectQuery(
                                                        "SELECT * FROM MSCluster_NetworkInterface where Name ='" + nameNetwork + "'"));
            return (from ManagementObject queryObj in searcher.Get() select new NetworkInterfaceProperty(queryObj)).FirstOrDefault();
        }


        /// <summary>
        /// Get a Cluster
        /// </summary>
        ///<param name="scope">instance of ManagementScope</param>
        /// <returns>Cluster class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ClusterProperties GetCluster(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var searcher =
                new ManagementObjectSearcher(scope, new ObjectQuery(
                                                        "SELECT * FROM MSCluster_Cluster"));
            return (from ManagementObject queryObj in searcher.Get() select new ClusterProperties(queryObj)).FirstOrDefault();
        }


        /// <summary>
        /// Get Dependencies Resource list from a resource
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameResource">Resource name</param>
        /// <returns>Array of resource class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceProperty[] FindDependenciesResourceByResource(string nameResource, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_ResourceToDependentResource WHERE Antecedent = \"MSCluster_Resource.Name='" + nameResource + "'\""));
            var reslst = (from ManagementObject s in searcher.Get()
                          select s["Dependent"].ToString().Replace("MSCluster_Resource.Name=\"", "").Replace("\"", "")).ToList();
            return reslst.Select(res => GetResource(res.Replace("\\\\", "\\"), scope)).ToArray();
        }

        /// <summary>
        /// Geta Disk list from a resource
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameResource">Resource name</param>
        /// <returns>Array of Disk class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal DiskProperty[] FindDisksByResource(string nameResource, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_ResourceToDisk  WHERE GroupComponent = \"MSCluster_Resource.Name='" + nameResource + "'\""));
            var dsklst = (from ManagementObject s in searcher.Get()
                          select s["PartComponent"].ToString().Replace("MSCluster_Disk.Name=\"", "").Replace("\"", "")).ToList();
            return dsklst.Select(dsk => GetDisk(dsk.Replace("\\\\", "\\"), scope)).ToArray();
        }


        /// <summary>
        /// Get a  possible owner nodes list from a Resource
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameResource">Resource name</param>
        /// <returns>Array of node class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal NodeProperty[] FindPossibleOwnerNodesByResource(string nameResource, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_ResourceToPossibleOwner  WHERE GroupComponent = \"MSCluster_Resource.Name='" + nameResource + "'\""));
            var nodes = (from ManagementObject s in searcher.Get()
                         select s["PartComponent"].ToString().Replace("MSCluster_Node.Name=\"", "").Replace("\"", "")).ToList();
            return nodes.Select(n => GetNode(n, scope)).ToArray();
        }

        /// <summary>
        /// Geta Resource list from a resourcetype
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <param name="nameResourcetype">Resource name</param>
        /// <returns>Array of Resource class</returns>
        ///<exception>
        /// this method throws exception for the following conditions:
        /// failed Scope Connect, 
        /// Failed WMI method execution
        /// </exception>
        internal ResourceProperty[] FindResourcesByResourceType(string nameResourcetype, ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();

            var searcher = new ManagementObjectSearcher(scope, new ObjectQuery(
                "SELECT * FROM MSCluster_ResourceTypeToResource  WHERE GroupComponent = \"MSCluster_ResourceType.Name='" + nameResourcetype + "'\""));
            var reslst = (from ManagementObject s in searcher.Get()
                          select s["PartComponent"].ToString().Replace("MSCluster_Resource.Name=\"", "").Replace("\"", "")).ToList();
            return reslst.Select(res => GetResource(res.Replace("\\\\", "\\"), scope)).ToArray();
        }

        /// <summary>
        /// Get Event Resource State Change
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>ManagementEventWatcher object</returns>
        internal ManagementEventWatcher GetEventResourceStateChange(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var query = new EventQuery("SELECT * FROM MSCluster_EventResourceStateChange");
            return new ManagementEventWatcher(scope, query);
        }

        /// <summary>
        /// Get Event Group State Change
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>ManagementEventWatcher object</returns>
        internal ManagementEventWatcher GetEventGroupStateChange(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var query = new EventQuery("SELECT * FROM MSCluster_EventGroupStateChange");
            return new ManagementEventWatcher(scope, query);
        }

        /// <summary>
        /// Get Event Cluster Object Add
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>ManagementEventWatcher object</returns>
        internal ManagementEventWatcher GetEventClusterObjectAdd(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var query = new EventQuery("SELECT * FROM MSCluster_EventObjectAdd");
            return new ManagementEventWatcher(scope, query);
        }

        /// <summary>
        /// Get Event Cluster Object Remove
        /// </summary>
        /// <param name="scope">instance of ManagementScope</param>
        /// <returns>ManagementEventWatcher object</returns>
        internal ManagementEventWatcher GetEventClusterObjectRemove(ManagementScope scope)
        {
            if (!scope.IsConnected) scope.Connect();
            var query = new EventQuery("SELECT * FROM MSCluster_EventObjectRemove");
            return new ManagementEventWatcher(scope, query);
        }

    }
}
